/*
 *      This program is free software; you can redistribute it and/or modify
 *      it under the terms of the GNU General Public License as published by
 *      the Free Software Foundation; either version 2 of the License, or
 *      (at your option) any later version.
 *      
 *      This program is distributed in the hope that it will be useful,
 *      but WITHOUT ANY WARRANTY; without even the implied warranty of
 *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *      GNU General Public License for more details.
 *      
 *      You should have received a copy of the GNU General Public License
 *      along with this program; if not, write to the Free Software
 *      Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 *      MA 02110-1301, USA.
 */

package bgtp;

import java.util.*;
import java.lang.*;
import java.util.regex.*;

public class ASTNode
{
    public ASTNode		left;
    public ASTNode		right;
    public String		value;
    public ASTNode		back;
    public CompareCallback	cCmp;

    private TreeMap<String, String>	stuff;

    public ASTNode(ASTNode parent)
    {
	back  = parent;
	value = null;
	left  = null;
	right = null;
	cCmp  = null;
    }
    
    public void destroy()
    {
	if(left != null)
	    {
		left.destroy();
		left = null;
	    }

	if(right != null)
	    {
		right.destroy();
		right = null;
	    }
	cCmp  = null;
	value = null;
    }

    public void markNode(String type)
    {
	if(type.equals("=") == true)
	    {
		cCmp  = new EquCallback();
	    }
	else if(type.equals("~") == true)
	    {
		cCmp  = new RequCallback();
	    }
	else if(type.equals("&") == true)
	    {
		cCmp  = new AndCallback();
	    }
	else if(type.equals("|") == true)
	    {
		cCmp  = new OrCallback();
	    }
	else if(type.equals("!=") == true)
	    {
		cCmp  = new NotCallback();
 	    }
    }

    public boolean call(TreeMap<String, String> stuff_)
    {
	stuff = stuff_;
	return call();
    }

    public boolean call()
    {
	//System.out.println("Self:"+this+" Parent:"+back+" Left:"+left+" Right:"+right);
	return cCmp.cmp(left, right);
    }

    public interface CompareCallback
    {
	public boolean cmp(ASTNode first, ASTNode second);
    }

    public class EquCallback implements CompareCallback
    {
	public boolean cmp(ASTNode first, ASTNode second)
	{
	    if(stuff.containsKey(left.value) == false)
		{
		    return false;
		}
	    return stuff.get(left.value).equals(right.value); 
	}
    }

    public class RequCallback implements CompareCallback
    {
	private Pattern regex = null;
	private Matcher tmp;
 
	public boolean cmp(ASTNode first, ASTNode second)
	{
	    if(stuff.containsKey(left.value) == false)
		{
		    return false;
		}
	    //здесь регэкспы
	    if(regex == null)
		{
		    //сначала обгрызть запятушки
		    int len = right.value.length();
		    regex   = Pattern.compile(right.value.substring(1,len-1));
		}
	    tmp = regex.matcher(stuff.get(left.value));
	    return tmp.matches();
	}
    }

    public class AndCallback implements CompareCallback
    {
	public boolean cmp(ASTNode first, ASTNode second)
	{
	    return first.call(stuff) & second.call(stuff);
	}
    }

    public class OrCallback implements CompareCallback
    {
	public boolean cmp(ASTNode first, ASTNode second)
	{
	    return first.call(stuff) | second.call(stuff);
	}
    }

    public class NotCallback implements CompareCallback
    {
	public boolean cmp(ASTNode first, ASTNode second)
	{
	    return  !stuff.get(first.value).equals(second.value);
	}
    }
}